import json
from datetime import datetime
from flask import Blueprint, render_template, request, jsonify, current_app
from sqlalchemy import delete, text
from applications.common.curd import model_to_dicts
from applications.common.helper import ModelFilter
from applications.common.utils.validate import xss_escape
from applications.extensions import db
from applications.models import CourseInfo, EvalutionReference, EmotionResult, PoliceModels
from applications.common.utils.http import table_api, fail_api, success_api
from applications.schemas import CourseInfoSchema, EvalutionReferenceSchema, EmotionResultSchema

course_emotion_bp = Blueprint('courseEmotion', __name__, url_prefix='/course/emotion')


@course_emotion_bp.get('/')
def main():
    return render_template('admin/course/emotion/main.html')


@course_emotion_bp.get('/data')
def data():
    # 获取请求参数
    courseName = xss_escape(request.args.get('course_name', type=str))
    courseType = xss_escape(request.args.get('course_type', type=str))

    # 查询参数构造
    mf = ModelFilter()
    if courseName:
        mf.contains(field_name="course_name", value=courseName)
    if courseType:
        mf.contains(field_name="course_type", value=courseTypeToId(courseType))
    # orm查询
    # 使用分页获取data需要.items
    course = CourseInfo.query.filter(mf.get_filter(model=CourseInfo)).with_entities(CourseInfo.course_id,
                                                                                    CourseInfo.course_name,
                                                                                    CourseInfo.course_detail,
                                                                                    CourseInfo.course_type).layui_paginate()
    count = course.total
    data = model_to_dicts(schema=CourseInfoSchema, data=course.items)
    for d in data:
        d.update(json.loads(d['course_detail'].replace('\'', '\"')))
        d['course_type'] = courseIdToType(d['course_type'])
    return table_api(data=data, count=count)


@course_emotion_bp.get('/add')
def getAddPage():
    return render_template('admin/course/emotion/add.html')


@course_emotion_bp.get('/cover')
def getPsychologyAddCover():
    return render_template('admin/course/emotion/cover.html')


@course_emotion_bp.post('/add')
def submitAdd():
    try:
        course = request.json
        course_details = json.dumps(
            {
                'course_details': course['course_description'],
                'person_gender': course['detail_gender'],
                'person_age': course['detail_age'],
                'person_mind': course['detail_mind'],
                'person_crime_types': course['detail_crime_type'],
                'person_tend': course['detail_tend'],
                'person_emotion': course['detail_emotion']
            },
            ensure_ascii=False
        )
        course_name = course['course_name']
        course_detail = course_details
        course_type = course['course_type']
        video_path = course['video_path']
        icon_path = str(course['course_icon'])
    except:
        return fail_api(msg="课程参数错误，请检查参数")

    # 根据图片url找到本地图片，打开为二进制文件
    try:
        with open('.' + icon_path.replace('_uploads/icons', current_app.config.get("UPLOADED_ICONS_DEST")), 'rb') as f:
            image_data = f.read()
    except FileNotFoundError:
        return fail_api(msg="课程封面不存在")

    courseInfo = CourseInfo(
        course_name=course_name,
        course_icon=image_data,
        course_detail=course_details,
        course_type=course_type,
        video_path=video_path,
        icon_path=icon_path
    )
    try:
        db.session.add(courseInfo)
        db.session.commit()
    except:
        return fail_api(msg="上传失败")
    res = {
        "msg": "上传成功",
        "code": 0,
        "success": True,
        "data":
            {"course_id": courseInfo.course_id}
    }
    return jsonify(res)


# 上传关键帧
@course_emotion_bp.post('/keypoint')
def setKeyPoint():
    try:
        data = request.json
        course_id = data['course_id']
        keypoints = data['key_points']
        for key_point in keypoints:
            evalutionReference = EvalutionReference(
                course_id=course_id,
                evaluation_id=int(key_point['id']),
                evalution_period_start_time=time_to_seconds(key_point['start']),
                evalution_period_end_time=time_to_seconds(key_point['end']),
                reference=key_point['emotion'],
                tone=key_point['tone']
            )
            db.session.add(evalutionReference)
    except:
        return fail_api(msg="已创建课程，关键帧参数错误，关键帧创建失败，请到编辑页面重新创建关键帧")
    try:
        db.session.commit()
    except:
        return fail_api(msg="已创建课程，关键帧创建失败，请到编辑页面重新创建关键帧")
    return success_api(msg="新增关键帧成功")


@course_emotion_bp.get('/edit/<int:course_id>')
def getEditPage(course_id):
    courseInfo = CourseInfo.query.filter_by(course_id=course_id).with_entities(CourseInfo.course_id,
                                                                               CourseInfo.course_name,
                                                                               CourseInfo.course_detail,
                                                                               CourseInfo.course_type,
                                                                               CourseInfo.video_path,
                                                                               CourseInfo.icon_path).one_or_none()
    if not courseInfo:
        return fail_api(msg='找不到课程信息')
    keypoints = model_to_dicts(schema=EvalutionReferenceSchema,
                               data=EvalutionReference.query.filter_by(course_id=course_id).all())
    courseInfoSchema = CourseInfoSchema()
    course_data = courseInfoSchema.dump(courseInfo)
    details = json.loads(course_data['course_detail'].replace('\'', '\"'))
    course_data.update(details)
    course_data['detail_gender'] = get_value_by_text('detail_gender', details['person_gender'])
    course_data['detail_crime_type'] = get_value_by_text('detail_crime_type', details['person_crime_types'])
    course_data['detail_age'] = get_value_by_text('detail_age', details['person_age'])
    course_data['detail_tend'] = get_value_by_text('detail_tend', details['person_tend'])
    course_data['detail_mind'] = get_value_by_text('detail_mind', details['person_mind'])
    course_data['detail_emotion'] = get_value_by_text('detail_emotion', details['person_emotion'])

    return render_template('admin/course/emotion/edit.html', courseInfo=course_data, keypoints=keypoints)


@course_emotion_bp.post('/edit')
def saveEdit():
    try:
        data = request.json
        course = data['courseInfo']
        keypoints = data['keypoints']
        deletedPoints = data['deletedPoints']
        course_id = course['course_id']
        course_name = course['course_name']
        course_type = course['course_type']
        video_path = course['video_path']
        icon_path = str(course['course_icon'])
        course_details = json.dumps(
            {
                'course_details': course['course_description'],
                'person_gender': course['detail_gender'],
                'person_age': course['detail_age'],
                'person_mind': course['detail_mind'],
                'person_crime_types': course['detail_crime_type'],
                'person_tend': course['detail_tend'],
                'person_emotion': course['detail_emotion']
            },
            ensure_ascii=False
        )
    except:
        return fail_api(msg="参数错误，更新失败")
    courseInfo = CourseInfo.query.filter_by(course_id=course_id).one_or_none()
    if not courseInfo:
        return fail_api(msg="找不到该课程")
    # 如果课程封面路径发生变化，则需要打开新图片，存储二进制文件
    if not courseInfo.icon_path == course['course_icon']:

        try:
            with open('.' + icon_path.replace('_uploads/icons', current_app.config.get("UPLOADED_ICONS_DEST")),
                      'rb') as f:
                image_data = f.read()
                courseInfo.course_icon = image_data
                courseInfo.icon_path = course['course_icon']
        except FileNotFoundError:
            return fail_api(msg="课程封面不存在")
    courseInfo.course_name = course_name
    courseInfo.course_detail = course_details
    courseInfo.course_type = course_type
    courseInfo.video_path = video_path

    # 删除被删除的关键帧
    deletedKeypoints = EvalutionReference.query.filter(EvalutionReference.evalution_index.in_(deletedPoints)).all()
    for point in deletedKeypoints:
        db.session.delete(point)

    # 更新关键帧及插入关键帧
    keypointList = EvalutionReference.query.filter_by(course_id=course_id).all()

    try:
        position = 0
        for point in keypoints:
            if 'evalution_index' in point:
                for p in keypointList:
                    if p.evalution_index == point['evalution_index']:
                        p.evaluation_id = position
                        p.evalution_period_start_time = time_to_seconds(point['start'])
                        p.evalution_period_end_time = time_to_seconds(point['end'])
                        p.reference = point['emotion']
                        p.tone = point['tone']
                        break
            else:
                evalutionReference = EvalutionReference(course_id=course['course_id'],
                                                        evaluation_id=position,
                                                        evalution_period_start_time=time_to_seconds(point['start']),
                                                        evalution_period_end_time=time_to_seconds(point['end']),
                                                        reference=point['emotion'],
                                                        tone=point['tone'])
                db.session.add(evalutionReference)
            position = position + 1
    except KeyError:
        return fail_api(msg="关键帧缺失参数，更新失败")
    try:
        db.session.commit()
    except:
        return fail_api(msg="更新失败")
    return success_api(msg="修改成功")


@course_emotion_bp.delete('/remove/<int:course_id>')
def delete(course_id):
    courseInfo = CourseInfo.query.filter_by(course_id=course_id).delete()
    if not courseInfo:
        return fail_api("找不到该课程")
    keypoints = EvalutionReference.query.filter_by(course_id=course_id).all()
    try:
        for keypoint in keypoints:
            db.session.delete(keypoint)
        db.session.commit()
    except:
        return fail_api("删除失败")
    return success_api("删除成功")


# 多个删除
@course_emotion_bp.delete('/batchRemove')
def batch_remove():
    try:
        ids = list(map(int, request.form.getlist('ids[]')))
    except:
        return fail_api(msg="找不到参数")
    # 由于使用SQLAlchemy的删除方法，必须要把被删除的数据传输到服务器端，图片二进制传输过慢，因此使用直接执行sql命令的形式
    try:
        stmt = text("DELETE FROM course_info WHERE course_id IN :ids")
        db.session.execute(stmt, params={"ids": ids})
        keypoints = EvalutionReference.query.filter(EvalutionReference.course_id.in_(ids)).all()
        for keypoint in keypoints:
            db.session.delete(keypoint)
        db.session.commit()
    except:
        return fail_api(msg="删除失败")
    return success_api(msg="删除成功")


@course_emotion_bp.get('/result')
def getResultPage():
    return render_template('admin/course/emotion/result.html')



@course_emotion_bp.get('/result/detail/<int:user_id>')
def result_details(user_id):
    # 获取请求参数
    course_Name = xss_escape(request.args.get('course_name', type=str))

    # 查询参数构造
    mf = ModelFilter()
    if course_Name:
        mf.contains(field_name="course_name", value=course_Name)

    results = EmotionResult.query.order_by('user_date').filter_by(user_id=user_id).layui_paginate()
    results_dict = model_to_dicts(schema=EmotionResultSchema, data=results.items)

    count = results.total
    return render_template('admin/course/emotion/result_detail.html', data=results_dict, count=count)



@course_emotion_bp.get('/result/detail/detail/<int:id>')
def result_detail_details(id):
    result = EmotionResult.query.filter_by(id=id).one_or_none()
    if result is None:
        return fail_api(msg="找不到该动作信息！")
    police = PoliceModels.query.filter_by(id=result.user_id).one_or_none()
    emotionresult = EmotionResult.query.filter_by(id=id).with_entities(EmotionResult.id,
                                                                           EmotionResult.user_id,
                                                                           EmotionResult.username,
                                                                           EmotionResult.user_course_types,
                                                                           EmotionResult.user_course_names,
                                                                           EmotionResult.user_course_details,
                                                                           EmotionResult.user_date,
                                                                           EmotionResult.user_grade,).one_or_none()
    if not emotionresult:
        return fail_api(msg='找不到课程信息')

    emotionresultSchema = EmotionResultSchema()
    course_data = emotionresultSchema.dump(emotionresult)
    details = json.loads(course_data['user_course_details'].replace('\'', '\"'))
    course_data.update(details)
    course_data['detail_gender'] = get_value_by_text('detail_gender', details['person_gender'])
    course_data['details'] = get_value_by_text('details', details['course_details'])
    course_data['detail_crime_type'] = get_value_by_text('detail_crime_type', details['person_crime_types'])
    course_data['detail_age'] = get_value_by_text('detail_age', details['person_age'])
    course_data['detail_tend'] = get_value_by_text('detail_tend', details['person_tend'])
    course_data['detail_mind'] = get_value_by_text('detail_mind', details['person_mind'])
    course_data['detail_emotion'] = get_value_by_text('detail_emotion', details['person_emotion'])
    return render_template('admin/course/emotion/result_detail_detail.html',
                           result=course_data,
                           police=police)

@course_emotion_bp.delete('/result/batchRemove')
def result_batch_remove():
    try:
        ids = list(map(int, request.form.getlist('ids[]')))
    except:
        return fail_api(msg="找不到参数")
    results = EmotionResult.query.filter(EmotionResult.id.in_(ids)).delete()
    db.session.commit()
    return success_api()


# 根据course_type
def courseIdToType(course_type):
    if course_type == '1':
        return '解救人质'
    elif course_type == '2':
        return '安抚情绪'
    elif course_type == '3':
        return '沟通交流'
    elif course_type == '4':
        return '制止暴乱'
    elif course_type == '5':
        return '处理冲突'


def courseTypeToId(course_name):
    if course_name == '解救人质':
        course_type = '1'
    elif course_name == '安抚情绪':
        course_type = '2'
    elif course_name == '沟通交流':
        course_type = '3'
    elif course_name == '制止暴乱':
        course_type = '4'
    elif course_name == '处理冲突':
        course_type = '5'
    return course_type


def time_to_seconds(time_str):
    time_str = time_str.replace(' ', '')
    time_obj = datetime.strptime(time_str, '%H:%M:%S')
    seconds = (time_obj - datetime(1900, 1, 1)).total_seconds()
    return seconds


# 根据选项的value获得选项
def get_text_by_value(id, value):
    option_dict = {
        "detail_gender": {
            "1": "男性",
            "2": "女性"
        },
        "detail_crime_type": {
            "1": "经济犯",
            "2": "财产犯",
            "3": "暴力犯",
            "4": "其他类型犯罪"
        },
        "detail_age": {
            "1": "老年",
            "2": "壮年",
            "3": "青年",
            "4": "少年"
        },
        "detail_tend": {
            "1": "惯犯",
            "2": "偶犯"
        },
        "detail_mind": {
            "1": "常态犯",
            "2": "异常犯"
        },
        "detail_emotion": {
            "1": "激情犯",
            "2": "预谋犯"
        }
    }

    if id in option_dict:
        if value in option_dict[id]:
            return option_dict[id][value]
        else:
            return "Invalid value"
    else:
        return "Invalid id"


# 根据选项的text获得选项的value
def get_value_by_text(id, text):
    option_dict = {
        "detail_gender": {
            "男性": "1",
            "女性": "2"
        },
        "detail_crime_type": {
            "经济犯": "1",
            "财产犯": "2",
            "暴力犯": "3",
            "其他类型犯罪": "4"
        },
        "detail_age": {
            "老年": "1",
            "壮年": "2",
            "青年": "3",
            "少年": "4"
        },
        "detail_tend": {
            "惯犯": "1",
            "偶犯": "2"
        },
        "detail_mind": {
            "常态犯": "1",
            "异常犯": "2"
        },
        "detail_emotion": {
            "激情犯": "1",
            "预谋犯": "2"
        }
    }

    if id in option_dict:
        if text in option_dict[id]:
            return option_dict[id][text]
        else:
            return "0"
    else:
        return "0"
